<template>
  <view class="file">
    <uni-section :title="label" type="line" v-if="label">
      <view class="uploadGroup">
        <view class="box" v-for="(item,index) in imageFiles" :key="index">
          <image mode="aspectFill" :src="handleImageUrl(item.path)" @click="previewImages(index)"/>
          <view class="close" @click="deleteImage(index)" v-if="!readonly">x</view>
        </view>
        <slot></slot>
        <view class="box add" @click="chooseImage" v-if="!readonly && imageFileSize < limit">+</view>
      </view>
    </uni-section>
    <view class="uploadGroup" v-else>
      <view class="box" v-for="(item,index) in imageFiles" :key="index">
        <image mode="aspectFill" :src="handleImageUrl(item.path)" @click="previewImages(index)"/>
        <view class="close" @click="deleteImage(index)" v-if="!readonly">x</view>
      </view>
      <view class="box add" @click="chooseImage" v-if="!readonly && imageFileSize < limit">+</view>
    </view>
  </view>
</template>
<script>
import config from "../../config";

export default {
  name: "image-picker",
  props: {
    readonly: {
      type: Boolean,
      default: false
    },
    label: String,
    limit: {
      type: Number,
      default: 9
    },
    original: {
      type: Boolean,
      default: false
    },
    compressed: {
      type: Boolean,
      default: true
    },
    album: {
      type: Boolean,
      default: true
    },
    camera: {
      type: Boolean,
      default: true
    },
    value: {
      type: [String,Array],
      default: null
    }

  },
  data() {
    return {
      imageFiles: null
    }
  },
  created() {
    this.initImageFilesByValue(this.value);
  },
  watch:{
    value(val){
      this.initImageFilesByValue(val);
    }
  },
  computed: {
    sizeType(){
      if(!this.original && !this.compressed){
        console.warn("original和compressed不能同时关闭,自动开启compressed");
        return ['compressed'];
      }
      return this.original && this.compressed
          ? ['original', 'compressed']
          : (this.original ? ['original'] : ['compressed']);
    },
    sourceType(){
      if(!this.album && !this.camera){
        console.warn("album和camera不能同时关闭,自动开启album");
        return ['album'];
      }
      return this.album && this.camera
          ? ['album', 'camera']
          : (this.album ? ['album'] : ['camera']);
    },
    imageFileSize(){
      return this.imageFiles ? this.imageFiles.length : 0;
    },
    selectCount(){
      let limit = this.limit - this.imageFileSize;
      return limit < 1 ? 1 : limit;
    },
  },
  methods: {
    hasImageFile(){
      return this.imageFiles && this.imageFiles.length > 0;
    },
    uploadImages(){
      if(!this.imageFiles){
        return;
      }
      Promise.all(this.imageFiles.map(file=>{
        return new Promise((resolve,reject) => {
          if(!file.size){
            resolve(file.path);
            return;
          }
          uni.uploadFile({
            url: uni.url + 'common/uploadFile',
            header: {
              Authorization: "Bearer " + uni.getStorageSync("token"),
            },
            filePath: file.path,
            name: 'file',
            success: res => {
              let imgUrl = JSON.parse(res.data).data;
              if(imgUrl){
                resolve(imgUrl);
              }else {
                reject(file.name)
              }
            },
            fail: err=>{
              reject(err);
            }
          })
        })
      })).then(imageUrls=>{
        this.$emit("update:value",imageUrls);
        this.$emit("success",imageUrls);
      }).catch(error=>{
        console.log("上传文件失败,错误信息",error)
        uni.showToast({
          title: "上传失败",
          duration: 2000,
          icon: "none"
        });
      })
    },
    initImageFilesByValue(val){
      if(val){
        if(typeof val === "string"){
          if(val.includes(',')){
            this.imageFiles = val.split(',').map(item=>{
              return {path: item};
            });
          }else {
            this.imageFiles = [{path: val}];
          }
        }else {
          this.imageFiles = val.map(item=>{
            return {path: item};
          });
        }
      }else {
        this.imageFiles = null;
      }
    },
    previewImages(index){
      console.log("预览图片",index);
      let imagePaths = this.imageFiles.map(item=>this.handleImageUrl(item.path));
      uni.previewImage({
        urls: imagePaths,
        current: index
      });
    },
    deleteImage(index){
      console.log("删除图片",index);
      this.imageFiles.splice(index,1);
      this.$emit("change",this.imageFiles);
    },
    chooseImage(){
      console.log("选择图片");
      let self = this;
      uni.chooseImage({
        count: this.selectCount,
        sizeType: this.sizeType, //可以指定是原图还是压缩图
        sourceType: this.sourceType, //可以指定从相册选择和拍照
        success: function (res) {
          console.log("选择图片结果",res)
          self.imageFiles = self.imageFiles ? [...self.imageFiles,...res.tempFiles] : res.tempFiles;
          if(self.imageFiles.length > self.limit){
            self.imageFiles = self.imageFiles.slice(0,self.limit);
          }
          self.$emit("change",self.imageFiles);
        }
      });
    },
  },
}
</script>

<style lang="scss">
.uploadGroup{
  padding: 20rpx;
  // 图片和加号显示成一行
  display: flex;
  // 多个元素自动换行
  flex-wrap: wrap;
  .box{
    width: 200rpx;
    height: 200rpx;
    background: #eee;
    margin-right: 15rpx;
    margin-bottom: 15rpx;
    // 相对定位
    position: relative;
    // 有图片图片的宽高都是100% 使其根加号的框框一样大
    image{
      width: 100%;
      height: 100%;
    }
    // 有close选择器时
    .close{
      // 加定位 父级要加相对定位
      position: absolute;
      // 位置右上角
      right: 0;
      top: 0;
      width: 50rpx;
      height: 50rpx;
      background: rgba(0,0,0,0.7);
      color: #fff;
      border-radius: 0 0 0 80rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      padding-bottom: 16rpx;
      padding-left: 8rpx;
    }
  }
  .add{
    font-size: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #888;
  }
}
</style>
